package cn.bincker.mybatis.encrypt.reflection.factory.interceptor;

import cn.bincker.mybatis.encrypt.exception.DecryptException;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bind.annotation.*;
import org.apache.ibatis.reflection.property.PropertyNamer;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

@Slf4j
public class WaitDecryptGetterInterceptor {
    @SuppressWarnings("unused")
    @RuntimeType
    public static Object intercept(
            @This Object that,
            @Origin Method method,
            @SuperCall Callable<?> superCall,
            @FieldValue(SetEncryptFutureInterceptor.encryptFutureFieldName)Map<String, Future<?>> futureMap
    ) {
        try {
            if (futureMap == null) return superCall.call();
            var future = futureMap.get(PropertyNamer.methodToProperty(method.getName()));
            if (future == null) return superCall.call();
            return future.get();
        }catch (Throwable e){
            EncryptEntity encryptEntity = (EncryptEntity) that;
            var cls = encryptEntity.$getTargetClass();
            throw new DecryptException(cls, that, PropertyNamer.methodToProperty(method.getName()), e);
        }
    }
}
